/*************************************************
 * 描述: 通用表格模型模板类，支持任何继承自 QObject 且定义了 Q_PROPERTY 的实体类型
 *
 * File: generictablemodel.h
 * Author: shizhixin@mozihealthcare.cn
 * Date: 2025-10-17
 * Update: 
 * ************************************************/
#ifndef COREXI_COMMON_PC_GENERICTABLEMODEL_H
#define COREXI_COMMON_PC_GENERICTABLEMODEL_H

#include <QFont>
#include <QMetaProperty>
#include <controls/table/cxitablemodel.h>

template<typename T>
class GenericTableModel : public CxiTableModel
{
public:
	explicit GenericTableModel(const QList<cxitable::GridColumnConfig>& columnConfig, QObject* parent = nullptr)
		: CxiTableModel(parent)
	{
		setGridColumnConfig(columnConfig);
	}

	// 添加实体对象
	void addItem(T* item)
	{
		beginInsertRows(QModelIndex(), m_items.size(), m_items.size());
		m_items.append(item);
		endInsertRows();
	}

	bool removeItem(int index)
	{
		if (index < 0 || index >= m_items.size()) return false;
		beginRemoveRows(QModelIndex(), index, index);
		m_items.removeAt(index);
		endRemoveRows();
		return true;
	}

	void clear()
	{
		if (m_items.isEmpty()) return;
		beginRemoveRows(QModelIndex(), 0, m_items.size() - 1);
		m_items.clear();
		endRemoveRows();
	}

	QList<T*> items() const { return m_items; }
	T* itemAt(int index) const { return index >= 0 && index < m_items.size() ? m_items.at(index) : nullptr; }

protected:
	/**
	 * @brief 通过 QMetaObject 设置属性值
	 */
	bool setFieldData(const QModelIndex& index, int role, const QString& field, const QVariant& data) override
	{
		if (role != Qt::EditRole) return false;
		T* obj = itemAt(index.row());
		if (!obj) return false;

		const QMetaObject* metaObj = obj->metaObject();
		int propIndex = metaObj->indexOfProperty(field.toUtf8().constData());
		if (propIndex < 0) return false;

		QMetaProperty prop = metaObj->property(propIndex);
		if (!prop.isWritable()) return false;

		bool ok = prop.write(obj, data);
		if (ok)
			emit dataChanged(index, index, {role});

		return ok;
	}

	/**
	 * @brief 通过 QMetaObject 获取属性值
	 */
	QVariant fieldData(const QModelIndex& index, int role, const QString& field) const override
	{
		if (role != Qt::DisplayRole && role != Qt::EditRole) return QVariant();

		T* obj = const_cast<T*>(itemAt(index.row()));
		if (!obj) return QVariant();

		const QMetaObject* metaObj = obj->metaObject();
		int propIndex = metaObj->indexOfProperty(field.toUtf8().constData());
		if (propIndex < 0) return QVariant();

		QMetaProperty prop = metaObj->property(propIndex);
		return prop.read(obj);
	}

	int rowCount(const QModelIndex& parent) const override
	{
		Q_UNUSED(parent)
		return m_items.size();
	}

	int columnCount(const QModelIndex& parent) const override
	{
		Q_UNUSED(parent)
		return d_columns.size();
	}

	QVariant headerData(int section, Qt::Orientation orientation, int role) const override
	{
		if (orientation != Qt::Horizontal)
		{
			// 只处理水平表头
			return QVariant();
		}

		if (section < 0 || section >= d_columns.size())
		{
			return QVariant();
		}

		switch (role)
		{
		case Qt::DisplayRole:
			return d_columns[section].caption;
		case Qt::TextAlignmentRole:
			return static_cast<int>(d_columns[section].textAlignment);
		case Qt::FontRole:
			return d_columns[section].isBold ? QFont(QFont().defaultFamily(), -1, QFont::Bold) : QVariant();
		default:
			return QVariant();
		}
	}

	bool setHeaderData(int section, Qt::Orientation orientation, const QVariant& value, int role) override
	{
		if (orientation != Qt::Horizontal)
		{
			return false;
		}

		if (section < 0 || section >= d_columns.size())
		{
			return false;
		}

		if (role == Qt::TextAlignmentRole)
		{
			Qt::Alignment align = static_cast<Qt::Alignment>(value.toInt());
			d_columns[section].textAlignment = align;
			emit headerDataChanged(orientation, section, section);
			return true;
		}
		return false;
	}

private:
	void setGridColumnConfig(const QList<cxitable::GridColumnConfig>& columns)
	{
		d_columns = columns;
	}

private:
	QList<T*> m_items;
};


#endif //COREXI_COMMON_PC_GENERICTABLEMODEL_H